package net.ufrog.common.utils;

import net.ufrog.common.Caller;
import net.ufrog.common.CoreConfig;
import net.ufrog.common.Logger;
import net.ufrog.common.exception.ServiceException;

import java.io.*;
import java.nio.file.Path;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 文件工具
 * 
 * @author ultrafrog
 * @version 1.0, 2011-12-30
 * @since 1.0
 */
public class Files {

    private static final Pattern PATTERN_EXT 	= Pattern.compile("^.*\\.([^.]+)$");

    private static Properties mimeTypes;

    /** 构造函数 */
    private Files() {}

    /**
     * 读取文件
     *
     * @param path 文件路径
     * @return 响应文件对象
     */
    public static File getFile(String path) {
        try {
            return new File(Class.forName(Caller.caller(3).getClassName()).getResource(path).getPath());
        } catch (ClassNotFoundException e) {
            Logger.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * 读取路径
     *
     * @param path 文件路径
     * @return 文件实际路径
     */
    public static Path getPath(String path) {
        return getFile(path).toPath();
    }

    /**
     * 读取输入流
     *
     * @param path 文件路径
     * @return 输入流
     */
    public static InputStream getInputStream(String path) {
        try {
            return Class.forName(Caller.caller(3).getClassName()).getResourceAsStream(path);
        } catch (ClassNotFoundException e) {
            Logger.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * 读取文件扩展名
     *
     * @param filename 文件名
     * @return 文件扩展名
     */
    public static String getExt(String filename) {
        Matcher matcher = PATTERN_EXT.matcher(filename);
        if (matcher.matches()) return matcher.group(1);
        return "";
    }

    /**
     * 读取文件扩展名
     *
     * @param file 文件对象
     * @return 文件扩展名
     */
    public static String getExt(File file) {
        return getExt(file.getName());
    }

    /**
     * 读取扩展类型
     *
     * @return 扩展类型
     */
    public static Properties getMimeTypes() {
        if (mimeTypes == null) {
            try {
                mimeTypes = new Properties();
                mimeTypes.load(getInputStream(CoreConfig.FILE_MIMETYPES));
            } catch (IOException e) {
                throw new ServiceException("cannot load '" + CoreConfig.FILE_MIMETYPES + "'.", e);
            }
        }
        return mimeTypes;
    }

    /**
     * 读取扩展类型
     *
     * @param filename 文件名
     * @return 文件扩展类型
     */
    public static String getMimeType(String filename) {
        return getMimeTypes().getProperty(getExt(filename));
    }

    /**
     * 读取扩展类型
     *
     * @param file 文件对象
     * @return 文件扩展类型
     */
    public static String getMimeType(File file) {
        return getMimeType(file.getName());
    }

    /**
     * 转换成字节数组
     *
     * @param file 文件对象
     * @return 文件字节数组
     */
    public static byte[] toBytes(File file) {
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] bytes = new byte[fis.available()];
            if (fis.read(bytes) != fis.available()) Logger.warn("input stream length is not equals read length.");
            return bytes;
        } catch (IOException e) {
            throw new ServiceException("cannot to bytes.", e);
        }
    }

    /**
     * 转换成字节数组
     *
     * @param path 文件路径
     * @return 文件字节数组
     */
    public static byte[] toBytes(String path) {
        return toBytes(getFile(path));
    }

    /**
     * 读取文件所有行
     *
     * @param file 文件对象
     * @return 文件行串流
     */
    public static List<String> readLines(File file) {
        try (FileReader fileReader = new FileReader(file); BufferedReader reader = new BufferedReader(fileReader)) {
            return reader.lines().collect(Collectors.toList());
        } catch (IOException e) {
            throw new ServiceException(e.getMessage(), e);
        }
    }

    /**
     * 读取文件所有行
     *
     * @param path 文件路径
     * @return 文件行串流
     */
    public static List<String> readLines(String path) {
        return readLines(getFile(path));
    }

    /**
     * 读取文件
     *
     * @param file 文件对象
     * @param reduced 是否简化
     * @return 文件字符串内容
     */
    public static String readFile(File file, Boolean reduced) {
        StringBuilder content = new StringBuilder();
        readLines(file).forEach(line -> {
            if (reduced) {
                content.append(line.trim());
            } else {
                content.append(line).append("\r\n");
            }
        });
        return content.toString();
    }

    /**
     * 读取文件
     *
     * @param file 文件对象
     * @return 文件字符串内容
     */
    public static String readFile(File file) {
        return readFile(file, Boolean.TRUE);
    }

    /**
     * 读取文件
     *
     * @param path 文件路径
     * @param reduced 是否简化
     * @return 文件字符串内容
     */
    public static String readFile(String path, Boolean reduced) {
        return readFile(getFile(path), reduced);
    }

    /**
     * 读取文件
     *
     * @param path 文件路径
     * @return 文件字符串内容
     */
    public static String readFile(String path) {
        return readFile(getFile(path));
    }

    /**
     * 生成临时文件
     *
     * @return 临时文件
     */
    public static File generateTmpFile() {
        return new File(System.getProperty("java.io.tmpdir"), Codecs.uuid());
    }
}
